// tcp/server/main.go
package tcp_helper

import (
	"encoding/hex"
	"fmt"
	"net"
	"sync"
)

//管理所有连接
type Server struct {
	readed_pkgs  chan *Package //所有client共同保持一份
	client_table sync.Map      //id(用户标识) string([]byte类型转化为十六进制) -> *BaseClient
}

func CreateServer() *Server {
	svr := &Server{}
	svr.readed_pkgs = make(chan *Package)
	return svr
}

func (svr *Server) Listen() {
	listen, err := net.Listen("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Println("listen failed, err:", err)
		return
	}
	for {
		conn, err := listen.Accept() // 建立连接
		if err != nil {
			fmt.Println("accept failed, err:", err)
			continue
		}
		go svr.HandleConn(conn) // 启动一个goroutine处理连接
	}
}

//输出收到的消息
func (svr *Server) Recv() {
	for pkg := range svr.readed_pkgs {
		fmt.Printf("receive package: %v, %v", string(pkg.Id), string(pkg.Data))

		//测试代码，将收到的原样发出去
		svr.Send(pkg.Id, pkg.Data)
	}
}

//运行服务器
func (svr *Server) Run() {
	go svr.Recv()
	svr.Listen()
}

//发送消息 . 返回： 0 成功 -1 连接断开 -2 发送缓存已满 -3 客户id找不到连接
func (svr *Server) Send(id, data []byte) int {
	cli := svr.GetClient(id)
	if cli == nil {
		return -3
	}
	return cli.Send(id, data)
}

//获取客户端
func (svr *Server) GetClient(id []byte) *BaseClient {
	id_hex := hex.EncodeToString(id)
	cli, err := svr.client_table.Load(id_hex)
	if err {
		return nil
	} else {
		return cli.(*BaseClient)
	}
}

//设置客户端，返回是否添加成功(如果有其他连接没有断开，则添加失败)
func (svr *Server) SetClient(id []byte, cli *BaseClient) bool {
	id_hex := hex.EncodeToString(id)
	old_cli, err := svr.client_table.Load(id_hex)
	if !err && old_cli != nil {
		if old_cli.(*BaseClient).conn != nil {
			// 有老的连接没有断开, 则断开新的
			cli.conn.Close()
			cli.conn = nil
			return false
		}
		cli.RecoverClientData(old_cli.(*BaseClient))
	}
	svr.client_table.Store(id_hex, cli)
	return true
}

func (svr *Server) HandleConn(conn net.Conn) {
	// 建立连接后，必须先收到一条消息，才能获取到id
	read_buf := []byte{}
	for {
		var buf [readBufferSize]byte
		n, err := conn.Read(buf[:]) // 读取数据
		if err != nil {
			fmt.Println("read from conn failed, err:", err)
			conn.Close()
			return
		}

		//解析包，并放入通道
		read_buf = append(read_buf, buf[:n]...)
		pkg_lst := UnSerializePackage(&read_buf)
		if len(pkg_lst) > 0 {
			for i := 0; i < len(pkg_lst); i += 1 {
				if len(pkg_lst[i].Id) > 0 {
					cli := new(BaseClient)
					cli.id = pkg_lst[i].Id
					cli.conn = conn
					cli.readed_pkgs = svr.readed_pkgs //引用
					cli.to_write_pkgs = make(chan *Package, SendPackageCacheSize)
					cli.read_buf = []byte{}
					cli.write_buf = []byte{}

					svr.SetClient(cli.id, cli)
					go cli.handleRead()
					go cli.handleSend()
					return
				}
			}
		}
	}
}
